import { computed, ComputedRef, onMounted, reactive, ref } from 'vue';
import { ObjectUtil } from '@/utils/ObjectUtil';
import { Options } from '@/components/Table/types';
import { Ref, UnwrapNestedRefs } from '@vue/reactivity';

export type Query<T> = {
  [P in keyof T]?: T[P] extends Date ? [Date | null, Date | null] : T[P] | null;
};

export interface SearchControl<T> {
  choice: Ref<keyof T | null>;
  query: Query<T>;
}

export interface UseSearch<T> {
  choice: Ref<keyof T | null>;
  // query: Query<T, K>;
  query: UnwrapNestedRefs<Query<T>>;
  clearQuery: () => void;
  currentChoiceOption: ComputedRef<Options<T>[keyof T] | null>;
}

export const useSearch = <T>(defaultRecord: T, options: Options<T>): UseSearch<T> => {
  const choice = ref(null) as Ref<keyof T | null>;

  const getDefaultQuery = <T>(defaultRecord: T, options: Options<T>): Query<T> => {
    const clone = ObjectUtil.clone(defaultRecord) as unknown as Query<T>;
    ObjectUtil.keys(clone).forEach(key => {
      const option = options[key];
      if (option?.type === 'time') {
        (clone[key] as [Date | null, Date | null]) = [new Date(2000, 0, 1, 0, 0), new Date()];
      } else {
        (clone[key] as T[keyof T] | null) = null;
      }
    });
    return clone;
  };

  const query: UnwrapNestedRefs<Query<T>> = reactive(getDefaultQuery<T>(defaultRecord, options));

  const clearQuery = () => {
    Object.assign(query, getDefaultQuery<T>(defaultRecord, options));
  };

  const currentChoiceOption: ComputedRef<Options<T>[keyof T] | null> = computed(() => {
    if (choice.value) {
      return options[choice.value];
    } else {
      return null;
    }
  });

  onMounted(() => {
    clearQuery();
  });

  return {
    choice,
    query,
    clearQuery,
    currentChoiceOption,
  };
};
